home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / PCGPEV10.ZIP / ASM3.TXT < prev    next >
Text File  |  1994-05-10  |  16KB  |  527 lines

  1.  
  2.                   - ASMVLA01 - File I/O - 04/14/93 -
  3.  
  4.     Lately we have been quite busy with school, so this second issue is a 
  5. little behind schedule.  But that's life... This little issue will quickly
  6. show off the DOS file functions: read, write, open, close, create & others.  
  7. They are all pretty much the same, so there isn't a whole lot to go over.
  8. But, as a bonus, I'm going to throw in a bit about how to do a subroutine.
  9. Let's do the subroutine stuff first.
  10.  
  11. `Procedures' as they are called, are declared like this:
  12.  
  13. ────────────────────────────────────────────────────────────────────────────
  14.  
  15. PROC TheProcedure
  16.  
  17.     ...             ;do whatever..
  18.     
  19.     ret             ;MUST have a RET statement!
  20. ENDP TheProcedure
  21.  
  22. ────────────────────────────────────────────────────────────────────────────
  23.  
  24.     In the procedure, you can do basically anything you want, just at the 
  25. end of it, you say ret.  You can also specify how to call the PROC by putting
  26. a NEAR or FAR after the procedure name.  This tells the compiler whether
  27. to change segment AND offset, or just offset when the procedure is called.
  28. Note that if you don't specify, it compiles into whatever the default is for
  29. the current .MODEL (small = near, large = far)
  30.  
  31. ────────────────────────────────────────────────────────────────────────────
  32.  
  33. PROC TheProc NEAR
  34.  
  35.     ...
  36.  
  37.     ret             ;this compiles to `retn' (return near- pops offset off
  38. ENDP TheProc        ; stack only)
  39.  
  40.     OR
  41.  
  42. PROC TheProc FAR
  43.  
  44.     ...
  45.  
  46.     ret             ;compiles to `retf' pops both offset & segment off stack
  47. ENDP TheProc        ; pops offset first
  48.  
  49. ────────────────────────────────────────────────────────────────────────────
  50.  
  51.     That's basically all there is to that.  Note that if you REALLY wanted to
  52. be tricky, you could do a far jump by doing this:
  53.  
  54. ────────────────────────────────────────────────────────────────────────────
  55.     push    seg TheProc
  56.     push    offset TheProc
  57.     retf
  58. ────────────────────────────────────────────────────────────────────────────
  59.  
  60.     This would "return" you to the beginning of the procedure "TheProc"...
  61. This code is just to illustrate a point.  If you actually did something like
  62. this and compiled and executed it, it would bomb.  Know why?  What happens 
  63. when it hits the `ret' in the PROC?  Well it pops off the offset and puts 
  64. it in IP and then pops the segment and puts it in CS.  Who knows what was
  65. on the stack... will return to an unknown address and probably crash.  (It
  66. DEFINATELY will not continue executing your code.)
  67.  
  68.     Of course, the only stack operations are PUSH and POP.  All they do is 
  69. push or pop off the stack a word sized or a Dword sized piece of data.  NEVER
  70. under ANY circumstance try to push a byte sized piece of data!  The results 
  71. are unpredictable.  Well, not really, but just don't do it, ok?
  72.  
  73.     There are also two commands that'll save you some time and code space:
  74.  
  75. PUSHA and POPA (push all and Pop all)
  76.  
  77.     PUSHA pushes the general registers in this order:
  78.  
  79. AX, CX, DX, BX, SP, BP, SI, DI
  80.  
  81.     POPA pops the general registers in this order:
  82.  
  83. DI, SI, BP, (sp), BX, DX, CX, AX
  84.  
  85.     SP is different because popa does NOT restore the value of SP.  It merely 
  86. pops it off and throws it away.
  87.  
  88.     For the 386+, pushad and popad push and pop all extended registers in
  89. the same order.  You don't need to memorize the order, because you don't
  90. need to know the order until you go and get tricky. (hint: the location of
  91. AX on the stack is [sp + 14] - useful if you want to change what AX returns,
  92. but you did a pusha cause you wanted to save all the registers (except AX)
  93. Then you'd do a popa, and AX= whatever value you put in there.
  94.  
  95.     ────
  96.  
  97.     Alright, now a slightly different topic: memory management
  98.  
  99.     Ok, this isn't true by-the-book memory management, but you need to know
  100. one thing:  Upon execution of a program, DOS gives it ALL memory up to the
  101. address A000:0000. This happens to be the beginning of the VGA buffer...
  102. Another thing you must know is that, if you used DOSSEG at the top of your
  103. file, the segment is the last piece of your program.  The size of the segment
  104. is derived from the little command `STACK 200h' or whatever the value was
  105. that you put up there.  The 200h is the number of bytes in the stack.  To get
  106. the number of paragraphs, you'd divide by 16.  Here's an example of how I can
  107. get a pointer to the first valid available segment that I can use for data:
  108.  
  109. ────────────────────────────────────────────────────────────────────────────
  110.     mov     ax,ss       ;grab the stack segment
  111.     add     ax,200h/16  ;add the size of the stack 200h/16 = 20h
  112.  
  113.     ;AX now contains the value of the first available segment the you can
  114.     ; use.
  115. ────────────────────────────────────────────────────────────────────────────
  116.  
  117.     This is very nice, because you can just plop your data right there
  118. and you have a 64k buffer you can use for anything you want.
  119.  
  120.     Ok, say you want to find out how much memory is available to use.  This
  121. would be done like this:  (no suprises, I hope.)
  122.  
  123. ────────────────────────────────────────────────────────────────────────────
  124.     mov     ax,ss       ;grab the stack segment
  125.     add     ax,200h/16  ;add the size of the stack 200h/16 = 20h
  126.     mov     bx,0A000h   ;upper limit of the free memory
  127.     sub     bx,ax       ;bx= # of paragraphs available
  128. ────────────────────────────────────────────────────────────────────────────
  129.  
  130.     Pretty darn simple.  That's enough of the overhead that you must know
  131. to understand the included ANSI viewer (asm3.asm)  
  132.  
  133.         Now to the FILE I/O stuff...
  134.  
  135.     Files can be opened, read from, written to, created, and closed.  To open
  136. a file, all you need to do is give the DOS interrupt a name & path.  All
  137. references to that file are done through what's known as a file handle. A
  138. file handle is simply a 16bit integer that DOS uses to identify the file.
  139. It's used more or less like an index into chart of pointers that point to 
  140. a big structure that holds all the info about the file- like current position
  141. in the file, file type, etc.. all the data needed to maintain a file.
  142. The `FILES= 20' thing in your autoexec simply tells DOS how much memory to
  143. grab for those structures. ( Files=20 grabs enough room for 20 open files. )
  144.  
  145.     ANYway, here's each of the important function calls and a rundown on what
  146. they do and how to work them.
  147.  
  148. ────────────────────────────────────────────────────────────────────────────
  149. FILE OPEN: Function 3Dh
  150.  
  151.  IN:
  152.     ah= 3Dh
  153.     al= open mode
  154.  
  155.         bits 7-3: Stuff that doesn't matter to us
  156.         bits 2-0: Access code
  157.             000 read only access
  158.             001 write only access
  159.             010 read and write access
  160.  
  161.     DS:DX= pointer to the ASCIIZ filename
  162.         ASCIIZ means that its an ASCII string with a Zero on the end.
  163.  
  164.  Returns:
  165.         CF=1 error occured
  166.             AX= error code- don't worry about what they are, if the carry
  167.                 is set, you didn't open the file.
  168.  
  169.         CF=0 no error
  170.             AX= File Handle ;you need to keep this- it's your only way to
  171.                             ; reference your file!
  172.  
  173.   ──── EXAMPLE ────
  174.  
  175.     [...]   ;header stuff
  176.  
  177.     .CODE           ;this stuff is used for all the examples
  178.  
  179.   FileName  db "TextFile.TXT",0
  180.   FileHandle dw 0
  181.   Buffer    db  300 dup (0)
  182.   BytesRead dw  0
  183.   FileSize  dd  0
  184.  
  185.     [...]   ;more stuff
  186.  
  187.     mov     ax,3d00h    ; open file for read only
  188.     mov     ax,cs
  189.     mov     ds,ax       ;we use CS, cause it's pointing to the CODE segment
  190.                         ; and our file name is in the code segment
  191.     mov     dx,offset FileName
  192.     int     21h
  193.     jc      FileError_Open
  194.  
  195.     mov     [FileHandle],ax
  196.  
  197.     [...]   ;etc...
  198.  
  199. ────────────────────────────────────────────────────────────────────────────
  200. FILE CLOSE: Function 3Eh
  201.  
  202.   IN:
  203.     AH= 3Eh
  204.     BX= File Handle
  205.  
  206.   RETURN:
  207.     CF=1 error occured, but who cares?
  208.   
  209.   ──── EXAMPLE ────
  210.  
  211.     mov     bx,[FileHandle]
  212.     mov     ah,3eh
  213.     int     21h
  214.  
  215. ────────────────────────────────────────────────────────────────────────────
  216. FILE READ: Function 3Fh
  217.  
  218.   IN:
  219.     AH= 3Fh
  220.     BX= File Handle
  221.     CX= Number of bytes to read
  222.     DS:DX= where to put data that is read from the file (in memory)
  223.     
  224.   RETURN:
  225.     AX= number of bytes actually read- if 0, then you tried to read from
  226.         the end of the file.
  227.  
  228.   ──── EXAMPLE ────
  229.  
  230.     mov     bx,[FileHandle]
  231.     mov     ax,cs
  232.     mov     ds,ax
  233.     mov     dx,offset buffer
  234.     mov     ah,3Fh
  235.     mov     cx,300
  236.     int     21h
  237.  
  238.     mov     [BytesRead],ax
  239.  
  240. ────────────────────────────────────────────────────────────────────────────
  241. FILE WRITE: Function 40h
  242.  
  243.   IN:
  244.     AH= 40h
  245.     BX= File Handle
  246.     CX= Number of bytes to write
  247.     DS:DX= where to read data from (in memory) to put on disk
  248.     
  249.   RETURN:
  250.     AX= number of bytes actually written- if not equal to the number of bytes
  251.         that you wanted to write, you have an error.
  252.         
  253.   ──── EXAMPLE ────
  254.  
  255.     mov     bx,[FileHandle]
  256.     mov     ax,cs
  257.     mov     ds,ax
  258.     mov     dx,offset buffer
  259.     mov     ah,40h
  260.     mov     cx,[BytesRead]
  261.     int     21h
  262.  
  263.     cmp     cx,ax
  264.     jne     FileError_Write
  265.  
  266. ────────────────────────────────────────────────────────────────────────────
  267. FILE CREATE: Function 3Ch
  268.  
  269.  IN:
  270.     ah= 3Ch
  271.     cl= file attribute
  272.  
  273.         bit 0: read-only
  274.         bit 1: hidden
  275.         bit 2: system
  276.         bit 3: volume label
  277.         bit 4: sub directory
  278.         bit 5: Archive
  279.         bit 6&7: reserved
  280.  
  281.     DS:DX= pointer to the ASCIIZ filename
  282.         ASCIIZ means that its an ASCII string with a Zero on the end.
  283.  
  284.  Returns:
  285.         CF=1 error occured
  286.             AX= error code- don't worry about what they are, if CF
  287.                 is set, you didn't create the file.
  288.  
  289.         CF=0 no error
  290.             AX= File Handle ;you need to keep this- it's your only way to
  291.                             ; reference your file!
  292.   ──── EXAMPLE ────
  293.  
  294.     mov     ah,3ch
  295.     mov     ax,cs
  296.     mov     ds,ax       ;we use CS, cause it's pointing to the CODE segment
  297.                         ; and our file name is in the code segment
  298.     mov     dx,offset FileName
  299.     mov     cx,0        ;no attributes
  300.     int     21h
  301.     jc      FileError_Create
  302.  
  303.     mov     [FileHandle],ax
  304.  
  305. ────────────────────────────────────────────────────────────────────────────
  306. FILE DELETE: Function 41h
  307.  
  308.  IN:
  309.     ah= 41h
  310.     DS:DX= pointer to the ASCIIZ filename
  311.     
  312.  Returns:
  313.         CF=1 error occured
  314.             AX= error code- 2= file not found, 3= path not found
  315.                     5= access denied
  316.  
  317.         CF=0 no error
  318.  
  319.   ──── EXAMPLE ────
  320.  
  321.     mov     ah,41h      ;kill the sucker
  322.     mov     ax,cs
  323.     mov     ds,ax
  324.     mov     dx,offset FileName
  325.     int     21h
  326.     jc      FileError_Delete
  327.  
  328. ────────────────────────────────────────────────────────────────────────────
  329. FILE MOVE POINTER: Function 42h
  330.  
  331.  IN:
  332.     ah= 42h
  333.     BX= File Handle
  334.     CX:DX= 32 bit pointer to location in file to move to    
  335.     AL= 0  offset from beginning of file
  336.       = 1  offset from curent position
  337.       = 2  offset from the end of the file
  338.       
  339.  Returns:
  340.         CF=1 error occured
  341.             AX= error code- no move occured
  342.  
  343.         CF=0 no error
  344.             DX:AX 32 bit pointer to indicate current location in file
  345.             
  346.   ──── EXAMPLE ────
  347.  
  348.     mov     ah,42h      ;find out the size of the file
  349.     mov     bx,[FileHandle]
  350.     xor     cx,cx
  351.     xor     dx,dx
  352.     mov     al,2
  353.     int     21h
  354.     
  355.     mov     [word low FileSize],ax
  356.     mov     [word high FileSize],dx ;load data into filesize
  357.  
  358.     (or in MASM mode, 
  359.  
  360.             mov word ptr [FileSize],ax
  361.             mov word ptr [FileSize+2],dx
  362.  
  363.     need I say why I like Ideal mode? )
  364.  
  365. ────────────────────────────────────────────────────────────────────────────
  366. FILE CHANGE MODE: Function 43h
  367.  
  368.  IN:
  369.     ah= 43h
  370.     DS:DX= pointer to the ASCIIZ filename
  371.     al= 0
  372.         returns file attributes in CX
  373.     al= 1 
  374.         sets file attributes to what's in CX
  375.     
  376.  Returns:
  377.         CF=1 error occured
  378.             AX= error code- 2= file not found, 3= path not found.
  379.                     5= access denied
  380.  
  381.         CF=0 no error
  382.  
  383.   ──── EXAMPLE ──── Lets erase a hidden file in your root directory...
  384.  
  385.   FileName db   "C:\msdos.sys",0
  386.  
  387.     [...]
  388.  
  389.     mov     ah,43h          ;change attribute to that of a normal file
  390.     mov     ax,cs
  391.     mov     ds,ax
  392.     mov     dx,offset FileName
  393.     mov     al,1            ;set to whats in CX
  394.     mov     cx,0            ;attribute = 0
  395.     int     21h
  396.  
  397.     mov     ah,41h          ;Nuke it with the delete command
  398.     int     21h
  399.  
  400. ────────────────────────────────────────────────────────────────────────────
  401.  
  402.     Well, that's all for now.  I hope this info is enough for you to do some 
  403. SERIOUS damage... :)  I just don't want to see any 'bombs' running around
  404. erasing the hidden files in the root directory, ok?
  405.  
  406.     Anyway, go take a look at asm3.asm- it's a SIMPLE ansi/text displayer.
  407. It just opens the file, reads it all into a "buffer" that was "allocated"
  408. immediatly after the stack & reads in the entire file (if it's < 64k) and 
  409. prints out the file character by character via DOS's print char (fn# 2).
  410. Very simple and very slow.  You'd need a better print routine to go faster...
  411. The quickest display programs would decode the ANSI on its own... But that's
  412. kinda a chore...  Oh, well.  Enjoy.
  413.  
  414.     Draeden/VLA
  415.  
  416.  
  417.     Suggested projects:
  418.  
  419.     1)  Write a program that will try to open a file, but if it does not
  420.         find it, the program creates the file and fills it with a simple
  421.         text message.
  422.  
  423.     2)  Write a program that will input your keystrokes and write them
  424.         directly to a text file.
  425.  
  426.     3)  The write & read routines actually can be used for a file or device.
  427.         Try to figure out what the FileHandle for the text screen is by
  428.         writing to the device with various file handles.  This same channel,
  429.         when read from, takes it's data from the keyboard.  Try to read data
  430.         from the keyboard.  Maybe read like 20 characters...  CTRL-Z is the 
  431.         end of file marker.
  432.  
  433.     4)  Try to use a file as `virtual memory'- open it for read/write access
  434.         and write stuff to it and then read it back again after moving the 
  435.         cursor position.
  436.  
  437.  
  438.  
  439. ┌──────────┬───────────────────────────────────────────────────────────────
  440. │ ASM3.ASM │
  441. └──────────┘
  442.  
  443. ;   VERY, VERY simple ANSI/text viewer
  444. ;
  445. ;   Coded by Draeden [VLA]
  446. ;
  447.  
  448.     DOSSEG
  449.     .MODEL SMALL
  450.     .STACK 200h
  451.     .CODE
  452.     Ideal
  453.  
  454. ;===- Data -===
  455.  
  456. BufferSeg   dw  0
  457.  
  458. ErrMsgOpen  db  "Error opening `"
  459. FileName    db  "ANSI.TXT",0,8,"'$"     ;8 is a delete character
  460.                                         ;0 is required for filename 
  461.                                         ;(displays a space)
  462. FileLength dw 0
  463.  
  464. ;===- Subroutines -===
  465.  
  466. PROC DisplayFile NEAR
  467.     push    ds
  468.  
  469.     mov     ax,cs
  470.     mov     ds,ax
  471.     mov     ax,3d00h    ;open file (ah=3dh)
  472.     mov     dx,offset FileName
  473.     int     21h
  474.     jc      OpenError
  475.     mov     bx,ax       ;move the file handle into bx
  476.  
  477.     mov     ds,[BufferSeg]
  478.     mov     dx,0            ;load to [BufferSeg]:0000
  479.     mov     ah,3fh
  480.     mov     cx,0FFFFh       ;try to read an entire segments worth
  481.     int     21h
  482.  
  483.     mov     [cs:FileLength],ax
  484.  
  485.     mov     ah,3eh
  486.     int     21h             ;close the file
  487.  
  488.     cld
  489.     mov     si,0
  490.     mov     cx,[cs:FileLength]
  491. PrintLoop:
  492.     mov     ah,2
  493.     lodsb
  494.     mov     dl,al
  495.     int     21h         ;print a character
  496.  
  497.     dec     cx
  498.     jne     PrintLoop
  499.     
  500.     pop     ds
  501.     ret
  502.  
  503. OpenError:
  504.     mov     ah,9
  505.     mov     dx,offset ErrMsgOpen
  506.     int     21h
  507.  
  508.     pop     ds
  509.     ret
  510. ENDP DisplayFile
  511.  
  512. ;===- Main Program -===
  513.  
  514. START:
  515.     mov     ax,cs
  516.     mov     ds,ax
  517.     mov     bx,ss
  518.     add     bx,200h/10h     ;get past the end of the file
  519.     mov     [BufferSeg],bx  ;store the buffer segment
  520.  
  521.     call    DisplayFile
  522.  
  523.     mov     ax,4c00h
  524.     int     21h
  525. END START
  526.  
  527.